const PROMISE_STATUS_PENDING = "PROMISE_STATUS_PENDING";
const PROMISE_STATUS_FULFTLLED = "PROMISE_STATUS_FULFTLLED";
const PROMISE_STATUS_REJECTED = "PROMISE_STATUS_REJECTED";

function withErr(fn, value, resolve, reject) {
  try {
    let result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
}
function Mypromise(execacrt) {
  this.status = PROMISE_STATUS_PENDING;
  this.onResolve = [];
  this.onReject = [];
  this.value = null;
  this.reason = null;
  const resolve = (value) => {
    queueMicrotask(() => {
      if (this.status == PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_FULFTLLED;
        this.value = value;
        this.onResolve.forEach((fn) => fn());
      }
    });
  };
  const reject = (reason) => {
    queueMicrotask(() => {
      if (this.status == PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_REJECTED;
        this.reason = reason;
        this.onReject.forEach((fn) => fn());
      }
    });
  };
  execacrt(resolve, reject);
}

Mypromise.prototype.then = function (onResolve, onReject) {
  return new Mypromise((resolve, reject) => {
    if (typeof onResolve !== "function") {
      onResolve = (value) => value;
    }
    if (typeof onReject !== "function") {
      onReject = (err) => {
        throw err;
      };
    }

    if (this.status == PROMISE_STATUS_FULFTLLED) {
      withErr(onResolve, this.value, resolve, reject);
    }
    if (this.status == PROMISE_STATUS_REJECTED) {
      withErr(onReject, this.reason, resolve, reject);
    }
    if (this.status == PROMISE_STATUS_PENDING) {
      this.onResolve.push(() => {
        withErr(onResolve, this.value, resolve, reject);
      });
      this.onReject.push(() => {
        withErr(onReject, this.reason, resolve, reject);
      });
    }
  });
};


Mypromise.prototype.catch = function (onReject) {
  return this.then(undefined, onReject);
};
Mypromise.prototype.finally = function (cb) {
  return this.then(
    (res) => cb(),
    (rej) => cb()
  );
};

Mypromise.all = function (promises) {
  return new Mypromise((resolve, reject) => {
    let result = [];
    for (const promise of promises) {
      promise
        .then((res) => {
          result.push(res);
          if (result.length == promises.length) {
            resolve(result);
          }
        })
        .catch(reject);
    }
  });
};
var promise = new Mypromise((resolve, reject) => {
  reject(222);
});
promise
  .then((res) => {
    console.log("res1", res);
  })
  .catch((err) => {
    console.log("catch", err);
  });
